package io.renren.controller;

import io.renren.common.exception.RRException;
import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.ProjectConstant;
import io.renren.common.utils.RedisUtils;
import io.renren.entity.MemberEntity;
import io.renren.entity.RoomEntity;
import io.renren.entity.SendPacketEntity;
import io.renren.form.RobotRange;
import io.renren.service.CenterService;
import io.renren.service.GrabPacketService;
import io.renren.service.MemberService;
import io.renren.service.RoomService;
import io.renren.service.SendPacketService;
import io.renren.service.SysConfigService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;

@EnableScheduling
@Component
public class TaskPacketAuto {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	MemberService memberService;

	@Autowired
	CenterService centerService;

	@Autowired
	RoomService roomService;

	@Autowired
	RedisUtils redisUtils;

	@Autowired
	SendPacketService sendPacketService;

	@Autowired
	GrabPacketService grabPacketService;

	@Autowired
	SysConfigService sysConfigService;

	private Map<Long, Long> lastSendTimeMap = new HashMap<Long, Long>();// 最后一次发包时间
	private Map<Long, Long> lastGrabTimeMap = new HashMap<Long, Long>();// 最后一次抢包时间
	private Map<Long, RobotRange> robotRangeMap = new HashMap<Long, RobotRange>();// 房间机器人范围

	/**
	 * 机器人
	 */
	private List<MemberEntity> members;

	@PostConstruct
	private void init() {
		// 初始化机器人
		members = memberService.selectList(new EntityWrapper<MemberEntity>().eq("user_level", ProjectConstant.USER_LEVEL_ROBOT));
	}

	/**
	 * 自动发红包定时任务
	 */
	@Scheduled(fixedDelay = 1000, initialDelay = 5000)
	public void robotSendTask() {
		if (!check()) {
			return;
		}

		// 允许机器人发包
		if (sysConfigService.getValueI(ConfigConstant.ENABLE_ROBOT_SEND) == ProjectConstant.COMMON_NO) {
			return;
		}

		// 先从缓存取room,如果没有再从数据库取
		List<RoomEntity> rooms = getRooms();
		if (CollectionUtils.isEmpty(rooms)) {
			return;
		}

		// 发包
		for (RoomEntity room : rooms) {
			// 控制发包频率
			Long lastSendTime = lastSendTimeMap.get(room.getId());
			if (lastSendTime != null && System.currentTimeMillis() < lastSendTime) {
				continue;
			}
			lastSendTimeMap.put(room.getId(), room.getRobotSendRate() + System.currentTimeMillis());
			// 百分之50概率发包
			if (RandomUtils.nextInt(0, 2) == 0) {
				try {
					// 机器人随机范围
					if (room.getRobotQty() == 99999) {
						robotRangeMap.remove(room.getId());
						continue;
					}
					RobotRange robotRange = getRobotRange(room.getId(), room.getRobotQty());
					sendPacketService.send(members.get(RandomUtils.nextInt(robotRange.getBegin(), robotRange.getEnd())), room.getId(), Double.valueOf(room.getMinAmount() * RandomUtils.nextInt(1, (room.getMaxAmount() / room.getMinAmount()) + 1)), RandomUtils.nextInt(1, 10),
							getQty(room.getPacketQty()));
				} catch (Exception e) {
					logger.error("机器人发包失败", e);
				}
			}
		}

	}

	/**
	 * 自动抢红包定时任务
	 */
	@Scheduled(fixedDelay = 1000, initialDelay = 5000)
	public void robotGrabTask() {
		if (!check()) {
			return;
		}

		// 允许机器人抢包
		if (sysConfigService.getValueI(ConfigConstant.ENABLE_ROBOT_GRAB) == ProjectConstant.COMMON_NO) {
			return;
		}

		// 先从缓存取room,如果没有再从数据库取
		List<RoomEntity> rooms = getRooms();
		if (CollectionUtils.isEmpty(rooms)) {
			return;
		}
		List<Long> roomIds = new ArrayList<Long>();
		for (RoomEntity room : rooms) {
			// 控制抢包频率
			Long lastGrabTime = lastGrabTimeMap.get(room.getId());
			if (lastGrabTime != null && System.currentTimeMillis() < lastGrabTime) {
				continue;
			}
			lastGrabTimeMap.put(room.getId(), room.getRobotGrabRate() + System.currentTimeMillis());
			roomIds.add(room.getId());
		}
		if (CollectionUtils.isEmpty(roomIds)) {
			return;
		}

		List<SendPacketEntity> sends = sendPacketService.selectList(new EntityWrapper<SendPacketEntity>().setSqlSelect("id,member_id,create_time").eq("status", ProjectConstant.PACKET_STATUS_INITIAL).in("room_id", roomIds));
		if (CollectionUtils.isNotEmpty(sends)) {
			for (SendPacketEntity send : sends) {
				try {
					// 百分之50概率抢包
					if (RandomUtils.nextInt(0, 2) == 0) {
						int begin = 0;
						int end = members.size();
						// 33%的概率发包者范围的机器人抢
						if (RandomUtils.nextInt(0, 3) == 0) {
							// 机器人随机范围
							RobotRange robotRange = getRobotRange(send.getRoomId(), 0);
							if (robotRange != null) {
								begin = robotRange.getBegin();
								end = robotRange.getEnd();
							}
						}
						MemberEntity member = members.get(RandomUtils.nextInt(begin, end));
						if (member.getId().equals(send.getMemberId())) {
							continue;
						} else if (System.currentTimeMillis() > DateUtils.addDateMinutes(send.getCreateTime(), sysConfigService.getValueI(ConfigConstant.PACKET_EXPIRE)).getTime()) {
							continue;
						}
						grabPacketService.grab(member, send.getId());
					}
				} catch (Exception e) {
					logger.error("机器人抢包失败:" + e.getMessage());
				}
			}
		}
	}

	/**
	 * 检查状态
	 * 
	 * @return
	 */
	private boolean check() {
		// 是否有机器人
		if (CollectionUtils.isEmpty(members)) {
			return false;
		}
		// 集群时只启动一个Task
		String ROBOT_TASK = redisUtils.get("ROBOT_TASK");
		if (ROBOT_TASK == null) {
			redisUtils.set("ROBOT_TASK", WebSocketRoom.UID, 600);// 十分钟
		} else if (!WebSocketRoom.UID.equals(ROBOT_TASK)) {
			return false;
		}
		return true;
	}

	/**
	 * 先从缓存取room,如果没有再从数据库取
	 * 
	 * @return
	 */
	private List<RoomEntity> getRooms() {
		List<RoomEntity> rooms = redisUtils.get("GAME_ROOMS", new TypeReference<List<RoomEntity>>() {
		});
		if (rooms == null) {
			rooms = roomService.selectList(new EntityWrapper<RoomEntity>().eq("enable_robot", ProjectConstant.COMMON_YES));
			redisUtils.set("GAME_ROOMS", rooms);
		}
		return rooms;
	}

	/**
	 * 获取机器人取值范围
	 * 
	 * @param roomId
	 * @param qty
	 * @return
	 */
	private RobotRange getRobotRange(Long roomId, int qty) {
		int robotCount = members.size();
		RobotRange robotRange = robotRangeMap.get(roomId);
		if (qty != 0 && robotRange == null) {
			if (robotCount <= qty) {
				robotRange = new RobotRange(0, robotCount);
			} else {
				int begin = RandomUtils.nextInt(0, robotCount - qty + 1);
				int end = begin + qty;
				robotRange = new RobotRange(begin, end);
			}
			robotRangeMap.put(roomId, robotRange);
		}
		return robotRange;
	}

	/**
	 * 随机发包数量
	 * 
	 * @param packetQty
	 * @return
	 */
	private int getQty(String packetQty) {
		try {
			String[] arrays = packetQty.split(",");
			String[] qr = arrays[RandomUtils.nextInt(0, arrays.length)].split("@");
			return Integer.parseInt(qr[0]);
		} catch (Exception e) {
		}
		throw new RRException("房间配置有误:发包数量无效");
	}
}
